package com.michael.demos.base.base.java.datastructure;


import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.TimeUnit;

/**
 * JAVA 容器类
 *
 * @author Michael
 */
public class ContainerDataTypeDemo {

    public static void main(String[] args) {

//        theArrayList();
//        theLinkedList();
//        theHashSet();
//        theLinkedHashSet();
        theTreeSet();
    }

    public static void theArrayList() {
        // ArrayList 底层使用 Object 数组,动态扩容每次1.5倍
        ArrayList<String> list = new ArrayList<>();
        // 为ArrayList添加线程安全
//        arrayList = Collections.synchronizedList(arrayList);

        // ArrayList扩容效率测试
        int count = 100000;

        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>(count);

        long time1 = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            list1.add("Michael" + i);
        }

        long time2 = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            list2.add("Michael" + i);
        }

        long time3 = System.currentTimeMillis();

        System.out.println("list1的长度：" + list1.size());
        System.out.println("list2的长度：" + list2.size());
        System.out.println("list1用时：" + (time2 - time1));
        System.out.println("list2用时：" + (time3 - time2));

    }

    public static void theLinkedList() {
        // LinkedList 底层使用双向链表,可以当作堆栈、队列或者双端队列使用
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("abc");
        linkedList.add("def");

        System.out.println("linkedList 头部数据\t" + linkedList.getFirst());
        System.out.println("linkedList 尾部数据\t" + linkedList.getLast());

    }

    public static void theHashSet() {
        // HashSet 底层使用HashMap实现，存储的数据是无序的、不重复的
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("hello");
        hashSet.add("Michael");
        hashSet.add("abc");
        hashSet.add("abc");

        System.out.println("HashSet无序性展示如下：(数据存储顺序为 hello Michael abc)");
        for (String s : hashSet) {
            System.out.println(s);
        }
    }

    public static void theLinkedHashSet() {
        // LinkedHashSet 继承自 HashSet,实现了有序
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("hello");
        linkedHashSet.add("Michael");
        linkedHashSet.add("abc");
        linkedHashSet.add("abc");

        System.out.println("linkedHashSet 有序性展示如下：(数据存储顺序为 hello Michael abc)");
        for (String s : linkedHashSet) {
            System.out.println(s);
        }
    }

    public static void theTreeSet() {
        // TreeSet 基于 TreeMap 实现,保证元素不重复且有序(支持自然排序与自定义排序，可以逆序进行输出)
        TreeSet<Integer> treeSet = new TreeSet<>();
        treeSet.add(4);
        treeSet.add(5);
        treeSet.add(3);
        treeSet.add(2);
        treeSet.add(3);
        treeSet.add(1);

        System.out.println("默认排序");
        for (int s : treeSet) {
            System.out.println(s);
        }

        // 自定义排序方式
        treeSet = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                if (o1 > o2) {
                    return -1;
                } else if (o1 < o2) {
                    return 1;
                }
                return 0;
            }
        });
        treeSet.add(4);
        treeSet.add(5);
        treeSet.add(3);
        treeSet.add(2);
        treeSet.add(3);
        treeSet.add(1);

        System.out.println("自定义排序");
        for (int s : treeSet) {
            System.out.println(s);
        }
    }

    public static void theArrayDeque() {
        // ArrayDeque 底层使用循环数组，可当作队列、堆栈使用
        ArrayDeque<String> arrayDeque = new ArrayDeque<>();
    }

    public static void theArrayBlockingQueue() {
        // TODO 线程安全的
        // ArrayBlockingQueue 底层使用循环数组,作为阻塞队列使用,内部由 ReentrantLock 来实现线程安全
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(16);

        // 1. 阻塞式插入
        try {
            arrayBlockingQueue.put("Michael");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 2. 非阻塞式插入,如果队列满了，直接返回 false 或者抛出异常(null)
        arrayBlockingQueue.offer("Michael");

        // 3. 综合1与2,向队列尾部插入数据，设置线程等待时间，如果超时后队列还是满的，返回false
        try {
            arrayBlockingQueue.offer("Michael", 1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 4. 队列满了直接抛异常，成功返回 true
        arrayBlockingQueue.add("Michael");

        // 5. 从头部获取元素,如果没有返回null
        arrayBlockingQueue.poll();

        // 6. 同poll,增加超时时间
        try {
            arrayBlockingQueue.poll(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 6. 从头部获取元素,并从队列中删除,如果队列空,等待并释放CPU
        try {
            arrayBlockingQueue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /** 延迟队列 */
    public static void theDelayQueue() {
        // TODO 线程安全的
        // DelayQueue 底层使用优先队列实现,队列中元素将在过期时被执行,复用组合了 PriorityQueue（策略者模式），让先过期的元素先执行
        DelayQueue delayQueue = new DelayQueue();
        // 元素需要实现 Delayed接口
    }

    /** 优先队列 */
    public static void thePriorityQueue() {
        // PriorityQueue 底层使用数组,默认大根堆,可自定义小根堆,可自定义比较器
        PriorityQueue priorityQueue = new PriorityQueue();
    }

    /**
     *
     */
    public static void theHashMap() {
        // HashMap 底层使用数组+链表/红黑树实现,支持扩容(成本高)
        HashMap<String, String> hashMap = new HashMap<>();
    }

    /**
     *
     */
    public static void theLinkedHashMap() {
        // LinkedHashMap 继承自 HashMap,增加有序性,可用于实现LRU算法
        LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
    }

    /**
     *
     */
    public static void theConcurrentHashMap() {
        // TODO 线程安全的
        // ConcurrentHashMap 分段锁技术,在确保线程安全的同时拥有不俗的性能,使用时要注意 Hash 碰撞的问题
        ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>();
    }

    /**
     *
     */
    public static void theTreeMap() {
        // TreeMap 底层使用红黑树,适用于Map中的KEY需要排序的场景
        TreeMap<String, String> treeMap = new TreeMap<>();

    }
}
